﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using IrrKlang;
using System.Threading;

using Scrobbler;

namespace Voize
{


    internal class CPlayer:ISoundStopEventReceiver
    {


        internal CPlayer( ref CPlaylist playlist,CPlayPosition PlayPosition,
                                                 CNotify notification,CInternetStream WebStream, CSettings settings)           
        {
            m_Engine = new ISoundEngine();
            m_Playlist = playlist;
            m_PlayPosition = PlayPosition;
            m_PlayingTimer = new System.Windows.Forms.Timer();
            m_PlayingTimer.Tick += new EventHandler(m_PlayingTimer_Tick);
            m_PlayingTimer.Interval = 1000;
            m_Notification = notification;
			m_WebStream = WebStream;
            m_Settings = settings;
           

        }


        private ISoundEngine m_Engine;
        private ISound m_SoundInfo;
        private string m_Name;
        private String m_Filename;
        private CPlaylist m_Playlist;
        private bool m_IsPaused = false;
        private CPlayPosition m_PlayPosition;
        private System.Windows.Forms.Timer m_PlayingTimer;
        private CNotify m_Notification;
		private CInternetStream m_WebStream;
        private CSettings m_Settings;
        private IScrobblerInfo m_ScrobblerInfo;
        private IScrobblerSubmitter m_ScrobblerSubmitter;
        private CVolume m_Volume;


        #region Scrobbler threading methods

        private void SubmitTrack()
        {
            try
            {
                if (CScrobblingSupport.Enabled)
                {
                    if (CScrobblingSupport.IsCreated == false)
                    {
                        if (this.ScrobblerHandshake())
                        {

                            CTrack track = new CTrack();
                            string artist = track.GetFirstArtist(m_Filename);
                            string song = track.GetSong(m_Filename);

                            if (artist != "" && song != "")
                            {
                                //MessageBox.Show(this.CurrentPlayTimeInSeconds);
                                //CLog.Write("["+DateTime.Now.ToString()+"]" + 
                                //" current playing time in seconds: " + this.CurrentPlayTimeInSeconds);
                                m_ScrobblerSubmitter.SubmitTrack(artist, song, this.CurrentPlayTimeInSeconds.ToString(),
                                    " ", " ", " ");
                            }
                        }
                        else
                            CLog.Write("Handshake returned false: Wrong username or password?");
                    }
                    else
                    {
                        CTrack track = new CTrack();
                        string artist = track.GetFirstArtist(m_Filename);
                        string song = track.GetSong(m_Filename);

                        if (artist != "" && song != "")
                        {
                            m_ScrobblerSubmitter.SubmitTrack(artist, song, this.CurrentPlayTimeInSeconds.ToString(),
                                " ", " ", " ");
                        }
                    }                
                }
            }
            catch (Exception ex)
            {
                CLog.Write("["+DateTime.Now.ToString()+"]" + " Error submitting the song because: " + ex.Message);
            }
        }



        private void SubmitPlayingNotification()
        {
            try
            {
                if (CScrobblingSupport.Enabled)
                {
                    if (CScrobblingSupport.IsCreated == false)
                    {
                        if (this.ScrobblerHandshake())
                        {
                            CTrack track = new CTrack();
                            string artist = track.GetFirstArtist(m_Filename);
                            string song = track.GetSong(m_Filename);

                            if (artist != "" && song != "")
                            {
                                m_ScrobblerSubmitter.SubmitPlayingNotification(artist, song,
                                " ", this.CurrentPlayTimeInSeconds.ToString(), " ", " ");
                            }
                        }
                        else
                            CLog.Write("Handshake returned false: Wrong username or password?");
                    }
                    else
                    {
                        CTrack track = new CTrack();
                        string artist = track.GetFirstArtist(m_Filename);
                        string song = track.GetSong(m_Filename);

                        if (artist != "" && song != "")
                        {
                            m_ScrobblerSubmitter.SubmitPlayingNotification(artist, song,
                            " ", this.CurrentPlayTimeInSeconds.ToString(), " ", " ");
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                CLog.Write("["+DateTime.Now.ToString()+"]" + " Error submitting playing notification because: " + ex.Message);
            }

        }


        private bool ScrobblerHandshake()
        {
            if (CScrobblingSupport.Enabled)
            {
                try
                {
                    IScrobbler scrobbler;
                    IScrobblerInfo ScrobblerInfo;
                    IScrobblerSubmitter ScrobblerSubmitter;
                    Factory ScrobblerFactory;
                    List<string> ResponseArray;

                    ScrobblerFactory = new Factory();
                    scrobbler = ScrobblerFactory.CreateScrobbler();
                    scrobbler.SetUser(m_Settings.User);
                    scrobbler.SetPassword(m_Settings.Password);

                    scrobbler.SetClientVersion(Application.ProductVersion);
                    scrobbler.SetClientID("vze");

                    ResponseArray = scrobbler.Handshake();

                    if (ResponseArray[0] == "BADAUTH")
                    {
                        CScrobblingSupport.IsCreated = false;
                        CLog.Write("[" + DateTime.Now.ToString() + "]" + " Handshake failed with response BADAUTH");
                        return false;
                    }

                    ScrobblerInfo = ScrobblerFactory.CreateScrobblerInfo(ResponseArray);

                    ScrobblerSubmitter = ScrobblerFactory.CreateScrobblerSubmitter(ScrobblerInfo);

                    m_ScrobblerInfo = ScrobblerInfo;
                    m_ScrobblerSubmitter = ScrobblerSubmitter;

                    CScrobblingSupport.IsCreated = true;
                    return true;
                }
                catch (Exception ex)
                {
                    CLog.Write("[" + DateTime.Now.ToString() + "]" + " scrobbler handshake problem because: " + ex.Message);
                    CScrobblingSupport.IsCreated = false;
                    return false;
                }
            }
            else
                return false;

        }



        #endregion

        internal void Play(string filename,float vol,float pan,float speed,CVolume volume)
        {
            try
            {
                if (System.IO.File.Exists(filename))
                {
                    m_Filename = filename;
                    m_Name = Path.GetFileName(filename);
                    m_Volume = volume;

                    this.Stop();
                    m_SoundInfo = m_Engine.Play2D(filename);

                    if (volume.IsMuted)
                    {
                        m_SoundInfo.Volume = 0.0F;
                    }
                    else
                    {
                        m_SoundInfo.Volume = vol;
                    }
                   
                    m_SoundInfo.Pan = pan;
                    m_SoundInfo.PlaybackSpeed = speed;

                    volume.SetSoundHandler(m_SoundInfo);

                    m_SoundInfo.setSoundStopEventReceiver(this);
                    CPlayerStatus.CanChangeSong = true;
                    this.m_IsPaused = false;
                    m_PlayPosition.SetMax((int)this.SoundLenght);
                    m_PlayingTimer.Start();

                    Thread th = new Thread(new ThreadStart(SubmitPlayingNotification));
                    th.Start();
                }
                else
                    m_Playlist.NextSong();

            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message);
            }
            
        }



        internal CVolume Volume
        {
            get { return m_Volume; }

        }



        internal void Stop()
        {
            CPlayerStatus.CanChangeSong = false;
            m_Engine.StopAllSounds();
        }



        internal void Pause(bool pause)
        {
            if (m_SoundInfo != null)
                m_SoundInfo.Paused = pause;

            if (pause == true)
                m_IsPaused = true;
            else
                m_IsPaused = false;
                
        }



        internal bool IsPaused
        {
            get { return m_IsPaused; }
        }



        internal String Filename
        {
            get { return m_Name; }
        }



        internal uint SoundLenght
        {
            get { return m_SoundInfo.PlayLength; }
        }



        internal uint CurrentPlayPosition
        {
            get { return m_SoundInfo.PlayPosition; }
        }



        internal string GetPlayingTime
        {
            get
            {
                if (m_SoundInfo != null)
                {
                    string pos;
                    string min;
                    string sec;

                    min = TimeSpan.FromMilliseconds(this.SoundLenght).Minutes.ToString();
                    sec = TimeSpan.FromMilliseconds(this.SoundLenght).Seconds.ToString();

                    if (min.Length == 1)
                        min = "0" + min;

                    if (sec.Length == 1)
                        sec = "0" + sec;

                    pos = min + ":" + sec;

                    return pos;
                }
                else
                    return "";
            }
        }



        private int CurrentPlayTimeInSeconds
        {
            get
            {
                return (int)TimeSpan.FromMilliseconds(this.SoundLenght).TotalSeconds;
            }
        }



        internal string GetCurrentPlayingPosition
        {
            get
            {
                string pos;
                string min;
                string sec;

                min = TimeSpan.FromMilliseconds(this.CurrentPlayPosition).Minutes.ToString();
                sec = TimeSpan.FromMilliseconds(this.CurrentPlayPosition).Seconds.ToString();

                if (min.Length == 1)
                    min = "0" + min;

                if (sec.Length == 1)
                    sec = "0" + sec;

                pos = min + ":" + sec;

                return pos;
            }
        }



        internal bool IsFinished
        {
            get { return m_SoundInfo.Finished; }
        }



        internal bool IsPlayingSong(string file)
        {
            if (m_Engine.IsCurrentlyPlaying(file))
                return true;
            else
                return false;
        }



        internal ISoundEngine PlayerEngine
        {
            get { return m_Engine; }
        }



        internal ISound Sound
        {
            get { return m_SoundInfo; }
        }



        internal void SetPlayPosition(uint position)
        {
            if(m_SoundInfo != null)
                if(position < this.SoundLenght && position >= 0)
                    m_SoundInfo.PlayPosition = position;
        }



        internal void ClearPlayPositionIndicatorValue()
        {
            m_PlayPosition.SetValue(0);
        }



        public void OnSoundStopped(ISound sound, StopEventCause reason, object userData)
        {

            Thread th = new Thread(new ThreadStart(SubmitTrack));
            th.Start();

            Thread.Sleep(TimeSpan.FromSeconds(0.5));

            if (CPlayerStatus.CanChangeSong == true)
            {
                m_Playlist.NextSong();
				Thread.Sleep(TimeSpan.FromSeconds(0.5));
                if (!m_Playlist.IsLastSongOnPlaylist)
                    m_Notification.Show("Now playing: " + 
                                                        m_Playlist.CurrentSongNameForPopUp + " " + 
                                                        this.GetPlayingTime, "Voize");
            }
           
        }



        void m_PlayingTimer_Tick(object sender, EventArgs e)
        {
            //Prevent unnecessary work and trackbar flickering when music is paused.
			if (m_WebStream.IsPlaying == false)
			{
				if (m_IsPaused == false)
					if (CPlayerStatus.PlayListLoaded == false)
					{
						m_PlayPosition.SetValue((int)this.CurrentPlayPosition);
					}
			}
        }



        internal CPlaylist Playlist
        {
            get { return m_Playlist; }
        }


    }
}
